home *** CD-ROM | disk | FTP | other *** search
- Subject: v17i094: Expand .mailrc aliases
- Newsgroups: comp.sources.unix
- Approved: rsalz@uunet.UU.NET
-
- Submitted-by: Mark Sirota <msir_cif@uhura.cc.rochester.edu>
- Posting-number: Volume 17, Issue 94
- Archive-name: malias
-
- malias: Decode mail aliases.
-
- Returns true address of all arguments, decoded from alias
- lines in your .mailrc.
-
- Results are returned in stream form, so
- % malias mark larry
- might return
- msir_ltd@uhura.cc.rochester.edu lm03_ltd@uhura.cc.rochester.edu
- so that the results can be passed on to some other program, as in
- % finger `malias cif`
- to finger everyone you know on CIF.
-
- --
- Mark Sirota - University of Rochester, Rochester, NY
- Internet: msir_cif@uhura.cc.rochester.edu
- Bitnet: msir_ss@uordbv.bitnet
- UUCP: ...!rochester!ur-cc!msir_cif
-
- #! /bin/sh
- # This is a shell archive. Remove anything before this line, then unpack
- # it by saving it into a file and typing "sh file". To overwrite existing
- # files, type "sh file -c". You can also feed this as standard input via
- # unshar, or by typing "sh <file", e.g.. If this archive is complete, you
- # will see the following message at the end:
- # "End of shell archive."
- # Contents: README Makefile malias.c malias.1
- # Wrapped by msir_cif@uhura.cc.rochester.edu on Tue Feb 7 15:38:48 1989
- PATH=/bin:/usr/bin:/usr/ucb ; export PATH
- if test -f 'README' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'README'\"
- else
- echo shar: Extracting \"'README'\" \(393 characters\)
- sed "s/^X//" >'README' <<'END_OF_FILE'
- X#
- X# README for malias
- X#
- X
- XThis program is Copyright (c) 1988, 1989 by Mark Sirota.
- XIt is provided to you without charge, and with no warranty.
- XYou may give away copies if malias, including sources, provided that this
- Xnotice is included in all the files.
- X
- XIn other words, you can do whatever you want with it, so long as you don't
- Xmake any money from it and credit is given where credit is due.
- END_OF_FILE
- if test 393 -ne `wc -c <'README'`; then
- echo shar: \"'README'\" unpacked with wrong size!
- fi
- # end of 'README'
- fi
- if test -f 'Makefile' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'Makefile'\"
- else
- echo shar: Extracting \"'Makefile'\" \(396 characters\)
- sed "s/^X//" >'Makefile' <<'END_OF_FILE'
- X#
- X# Makefile for malias
- X#
- X
- X#
- X# Update the following directories for your installation.
- X#
- XBINDIR = /u/cif/bin
- XMANDIR = /u/cif/man
- XMANEXT = 1
- X
- XCFLAGS = -O
- X
- Xmalias: malias.c
- X cc $(CFLAGS) -o malias
- X
- Xinstall: malias
- X install -s malias $(BINDIR)
- X install -m 0644 malias.1 $(MANDIR)/man$(MANEXT)/malias.$(MANEXT)
- X
- Xclean:
- X rm -f malias core
- X
- Xshar:
- X shar -o malias.shar README Makefile malias.c malias.1
- END_OF_FILE
- if test 396 -ne `wc -c <'Makefile'`; then
- echo shar: \"'Makefile'\" unpacked with wrong size!
- fi
- # end of 'Makefile'
- fi
- if test -f 'malias.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'malias.c'\"
- else
- echo shar: Extracting \"'malias.c'\" \(8203 characters\)
- sed "s/^X//" >'malias.c' <<'END_OF_FILE'
- X/*
- X * malias: Decode mail aliases. Returns true address of all arguments,
- X * decoded from alias lines in your .mailrc.
- X *
- X * Usage: malias <alias> [alias] ...
- X *
- X * Results are returned in stream form, so
- X * % malias mark larry
- X * might return
- X * msir_ltd@uhura.cc.rochester.edu lm03_ltd@uhura.cc.rochester.edu
- X * so that the results can be passed on to some other program, as in
- X * finger `malias cif`
- X * to finger everyone you know on CIF.
- X *
- X * Mark Sirota (msir_cif@uhura.cc.rochester.edu), Fall 1988
- X */
- X
- X/*
- X * The program reads the .mailrc and saves the aliases in trie format.
- X * The leaves of the trie are linked lists of addresses. Each address may
- X * itself be an alias.
- X *
- X * The name of the .mailrc is determined by the environment variable MAILRC.
- X * If not present, $HOME/.mailrc is assumed. The "-f" option overrides this.
- X */
- X
- X#include <stdio.h>
- X#include <string.h>
- X#include <malloc.h>
- X
- X/*
- X * Aliases are maintained as a binding of a name to a mailing list (which may
- X * contain one or more names). Names in a list may themselves be aliases.
- X * This structure is one of the names in a mailing list.
- X */
- Xstruct address {
- X char *address;
- X struct address *next,
- X *prev;
- X};
- X
- X/*
- X * Ways of finding an alias in the trie.
- X */
- X#define A_NOTFOUND -1 /* Not in the trie */
- X#define A_USED 0 /* Found, but already seen */
- X#define A_FOUND 1 /* Found and okay */
- X
- X#define FALSE 0
- X#define TRUE 1
- X
- Xvoid
- Xusage(progname)
- Xchar *progname;
- X{
- X fprintf(stderr, "Usage: %s [-,] [-1] [-f filename] <alias ...>\n", progname);
- X}
- X
- Xvoid
- Xmain(argc, argv)
- Xint argc;
- Xchar **argv;
- X{
- X int c;
- X extern int optind;
- X extern char *optarg;
- X int commaflag = FALSE;
- X int oneflag = FALSE;
- X char *filename = (char *) NULL;
- X char **root;
- X extern char *calloc();
- X void mailrc();
- X struct address *list = (struct address *) NULL,
- X *l,
- X *lprev;
- X void lookup();
- X
- X /*
- X * Parse the arguments.
- X */
- X while ((c = getopt(argc, argv, ",1f:")) != EOF)
- X switch (c) {
- X case ',':
- X commaflag = TRUE;
- X break;
- X case '1':
- X oneflag = TRUE;
- X break;
- X case 'f':
- X filename = optarg;
- X break;
- X case '?':
- X default:
- X usage(argv[0]);
- X exit(1);
- X }
- X
- X /*
- X * If there are no aliases to process, just exit. This is so that
- X * malias can be used as a front end for other programs, which don't
- X * necessarily take arguments, like finger.
- X */
- X if (optind == argc)
- X exit(0);
- X
- X /*
- X * Allocate memory for the root node of the trie
- X */
- X if (!(root = (char **) calloc(128, sizeof (char *)))) {
- X fprintf(stderr, "Out of memory.\n");
- X exit(1);
- X }
- X
- X /*
- X * Read lines out of the .mailrc, and add each alias to the trie
- X */
- X mailrc(filename, root);
- X
- X /*
- X * Translate argv to a linked list.
- X */
- X for (; optind < argc; optind++) {
- X if (!(l = (struct address *) malloc(sizeof (struct address)))) {
- X fprintf(stderr, "Out of memory.\n");
- X break;
- X }
- X
- X if (!list) {
- X list = l;
- X list->prev = (struct address *) NULL;
- X } else {
- X l->prev = lprev;
- X lprev->next = l;
- X }
- X l->address = argv[optind];
- X l->next = (struct address *) NULL;
- X lprev = l;
- X }
- X
- X /*
- X * Now look up the list
- X */
- X lookup(root, &list);
- X
- X /*
- X * Print the results.
- X */
- X for (l = list; l; l = l->next) {
- X fputs(l->address, stdout);
- X if (l->next) {
- X if (commaflag)
- X putchar(',');
- X if (oneflag)
- X putchar('\n');
- X else
- X putchar(' ');
- X }
- X }
- X putchar('\n');
- X}
- X
- X/*
- X * Open the user's .mailrc and add each alias to the trie. The .mailrc is
- X * defined by the environment variable MAILRC. If not found, $HOME/.mailrc
- X * is assumed.
- X *
- X * The mail command "source", if found in the mailrc, is followed.
- X */
- Xvoid
- Xmailrc(filename, root)
- Xchar *filename;
- Xchar **root;
- X{
- X extern char *getenv();
- X char buffer[BUFSIZ];
- X FILE *fp;
- X char line[BUFSIZ];
- X char *command;
- X char *alias;
- X char *salloc();
- X struct address *real;
- X struct address *lalloc();
- X void addalias();
- X
- X if (!filename && !(filename = getenv("MAILRC"))) {
- X sprintf(buffer, "%s/.mailrc", getenv("HOME"));
- X filename = buffer;
- X }
- X
- X if (!(fp = fopen(filename, "r"))) {
- X perror(filename);
- X exit(1);
- X }
- X
- X while (fgets(line, sizeof line, fp)) {
- X if (!(command = strtok(line, " \t\n")))
- X continue;
- X
- X if (strcmp(command, "source") == 0)
- X mailrc(strtok((char *) NULL, "\n"), root);
- X else if (strcmp(command, "alias") == 0) {
- X alias = salloc(strtok((char *) NULL, " \t"));
- X real = lalloc(strtok((char *) NULL, "\n"));
- X addalias(root, alias, real);
- X }
- X }
- X
- X fclose(fp);
- X}
- X
- X/*
- X * Add an alias to the trie
- X */
- Xvoid
- Xaddalias(root, alias, real)
- Xchar **root;
- Xchar *alias;
- Xstruct address *real;
- X{
- X char **tp;
- X extern char *calloc();
- X
- X /*
- X * Scan down the existing trie as far as we can
- X */
- X tp = root;
- X for (; *alias; alias++) {
- X if (!tp[*alias])
- X break;
- X tp = (char **) tp[*alias];
- X }
- X
- X /*
- X * Add the rest of the alias to the trie
- X */
- X for (; *alias; alias++) {
- X if (!(tp[*alias] = calloc(128, sizeof (char *)))) {
- X fprintf(stderr, "Out of memory.\n");
- X exit(1);
- X }
- X tp = (char **) tp[*alias];
- X }
- X
- X /*
- X * Set the end of the alias to point to the real name
- X */
- X tp[NULL] = (char *) real;
- X}
- X
- X/*
- X * Look up an alias list in the trie. When finished, the list will contain
- X * only resolved names.
- X */
- Xvoid
- Xlookup(root, aliasl)
- Xchar **root;
- Xstruct address **aliasl;
- X{
- X struct address *alias; /* Current alias pointer */
- X struct address *list,
- X *l; /* list associated with alias */
- X
- X /*
- X * Look up each alias in this list
- X */
- X alias = *aliasl;
- X while (alias) {
- X switch (findalias(root, alias->address, &list)) {
- X case A_NOTFOUND:
- X /*
- X * Leave this one alone.
- X */
- X alias = alias->next;
- X break;
- X case A_USED:
- X /*
- X * This alias has been processed before.
- X * just remove this alias and move on.
- X */
- X if (alias->prev)
- X alias->prev->next = alias->next;
- X else
- X *aliasl = alias->next;
- X if (alias->next)
- X alias->next->prev = alias->prev;
- X alias = alias->next;
- X break;
- X case A_FOUND:
- X /*
- X * Splice the list in here in place of the alias.
- X */
- X if (alias->prev)
- X alias->prev->next = list;
- X else
- X *aliasl = list;
- X list->prev = alias->prev;
- X for (l = list; l->next; l = l->next)
- X ;
- X l->next = alias->next;
- X if (alias->next)
- X alias->next->prev = l;
- X alias = list;
- X break;
- X }
- X }
- X}
- X
- X/*
- X * Find an alias in the trie. When an alias is fonund, the alias is removed
- X * so that it will not be repeated. The result is placed in list, and the
- X * status is returned (NOTFOUND, USED, or FOUND).
- X */
- Xint
- Xfindalias(root, alias, list)
- Xchar **root;
- Xchar *alias;
- Xstruct address **list;
- X{
- X char **tp;
- X
- X /*
- X * Scan down the trie
- X */
- X tp = root;
- X for (; *alias; alias++) {
- X if (!tp[*alias])
- X break;
- X tp = (char **) tp[*alias];
- X }
- X
- X /*
- X * If we didn't make it to the end of the alias, return NOTFOUND.
- X * Otherwise, return the list.
- X */
- X if (*alias) {
- X *list = (struct address *) NULL;
- X return A_NOTFOUND;
- X }
- X
- X /*
- X * Found. If used, the leaf will be NULL, and so we'll return USED.
- X */
- X if ((struct address *) tp[NULL] == (struct address *) NULL) {
- X *list = (struct address *) NULL;
- X return A_USED;
- X }
- X
- X /*
- X * Save a pointer to the list and then remove the trie
- X * reference. Next time this alias is referenced, it will return a
- X * NULL list.
- X */
- X *list = (struct address *) tp[NULL];
- X tp[NULL] = (char *) NULL;
- X return A_FOUND;
- X}
- X
- X/*
- X * Allocate enough new memory to hold string, copy it there, and return a
- X * pointer to the new copy.
- X */
- Xchar *
- Xsalloc(string)
- Xchar *string;
- X{
- X return strcpy(malloc((unsigned) strlen(string) + 1), string);
- X}
- X
- X/*
- X * Take a string and turn it into a linked list of addresses, using spaces
- X * and tabs as delimiters.
- X */
- Xstruct address *
- Xlalloc(string)
- Xchar *string;
- X{
- X char *s;
- X struct address *l,
- X *lprev,
- X *list = (struct address *) NULL;
- X char *salloc();
- X
- X for (s = strtok(string, " \t"); s; s = strtok((char *) NULL, " \t")) {
- X if (!(l = (struct address *) malloc(sizeof (struct address)))) {
- X fprintf(stderr, "Out of memory.\n");
- X return (struct address *) NULL;
- X }
- X if (!list) {
- X list = l;
- X list->prev = (struct address *) NULL;
- X } else {
- X list->prev = lprev;
- X lprev->next = l;
- X }
- X l->address = salloc(s);
- X l->next = (struct address *) NULL;
- X lprev = l;
- X }
- X
- X return list;
- X}
- END_OF_FILE
- if test 8203 -ne `wc -c <'malias.c'`; then
- echo shar: \"'malias.c'\" unpacked with wrong size!
- fi
- # end of 'malias.c'
- fi
- if test -f 'malias.1' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'malias.1'\"
- else
- echo shar: Extracting \"'malias.1'\" \(2311 characters\)
- sed "s/^X//" >'malias.1' <<'END_OF_FILE'
- X.TH MALIAS 1 "21 January 1989"
- X.SH NAME
- Xmalias \- expand mail aliases
- X.SH SYNOPSIS
- X\fBmalias\fP [\fB-,\fP] [\fB-1\fP] [\fB-f \fIfilename\fP] [\fIalias ...\fP]
- X.SH DESCRIPTION
- X\fBmalias\fP decodes alias lines from a mailrc and returns the true
- Xaddresses. By default, the results are returned in stream format so that
- Xthe results may be passed on to some other program (See the EXAMPLES section
- Xbelow).
- X
- XThe mailrc is determined by the environment variable \fBMAILRC\fP. If not
- Xset, \fBmalias\fP tries \fB$HOME/.mailrc\fP. An alternate filename may be
- Xspecified on the command line using the \fB-f\fP option (See the OPTIONS
- Xsection below). If the mail command \fBsource\fP is found in the mailrc, it
- Xis followed properly.
- X
- XIf an alias on the command line is not found in the mailrc, then it will be
- Xleft alone. An alias which is found twice (on the command line, as an
- Xalias, or as part of a mailing list) will only be returned once. Aliases
- Xmay be more than one level deep.
- X
- XIf no \fIalias\fP is given on the command line, \fBmalias\fP simply
- Xexits. This is so that it can be used as a front end processor for
- Xprograms which don't necessarily take arguments, such as \fBfinger(1)\fP.
- XSee the EXAMPLES section below.
- X.SH OPTIONS
- X.IP \fB-,\fP
- XDelimit output with commas. This is provided for compatibility with RFC822.
- X.IP \fB-1\fP
- XReturn addresses one per line instead of in stream format.
- X.IP "\fB-f \fIfilename\fP"
- XUse \fIfilename\fP as the mailrc instead of checking the environment
- Xvariable.
- X.SH EXAMPLES
- X.IP "\fBmalias -1 -f ~joss/.mailrc all | wc -l\fP"
- Xwould tell you how many people the user \fBjoss\fP has in his \fBall\fP
- Xlist.
- X.IP "\fBfinger `malias rochester`"
- Xwould \fBfinger\fP all the people in your \fBrochester\fP mailing list.
- X.IP "\fBtalk `malias mark`\fP"
- Xwould run the command \fBtalk msir_cif@uhura.cc.rochester.edu\fP. This
- Xcan be used in an alias, to make your life easier, as in...
- X.IP "\fBalias talk 'talk `malias \e!*`'\fP"
- Xso that whenever you run \fBtalk\fP, it will first look through your mail
- Xaliases for the address you specify.
- X.ad
- X.SH ENVIRONMENT
- X.IP \fBMAILRC\fP
- XName of mailrc file.
- X.SH FILES
- X.IP \fB~/.mailrc\fP
- Xdefault mailrc, if environment variable isn't found.
- X.SH "SEE ALSO"
- Xmail(1), Mail(1)
- X.SH AUTHOR
- XMark Sirota (msir_cif@uhura.cc.rochester.edu), Fall 1988
- END_OF_FILE
- if test 2311 -ne `wc -c <'malias.1'`; then
- echo shar: \"'malias.1'\" unpacked with wrong size!
- fi
- # end of 'malias.1'
- fi
- echo shar: End of shell archive.
- exit 0
-
-